package dcdroplet;

// Import Java JDK Classes
import java.io.File;
import java.io.IOException;
import java.util.Locale;

/**
 * The logger instance for DCDroplet logs.<br/>
 * @author dca
 */
public class DCDropletLogger {
	/** Logger name field for logging messages.<br/> */
	protected String name;

	/** The logging properties.<br/> */
	protected DCDropletProperties properties;

	/** Constructor<br/> */
	protected DCDropletLogger() {
		this("");
	} // END constructor

	/**
	 * Constructor<br/>
	 * @param clazz The class for logging messages.<br/>
	 */
	protected DCDropletLogger(final Class<?> clazz) {
		this(null != clazz ? clazz.getName() : "");
	} // END constructor

	/**
	 * Constructor<br/>
	 * @param name The name for logging messages.<br/>
	 */
	protected DCDropletLogger(final String name) {
		this.name = name;

		try {
			properties = new DCDropletProperties();
		} catch(IOException ioExc) {
			System.out.printf("ERROR in DCDropletLogger: IOException: %s%n", ioExc.getMessage());
			ioExc.printStackTrace();
		} catch(Exception exc) {
			System.out.printf("ERROR in DCDropletLogger: Exception: %s%n", exc.getMessage());
			exc.printStackTrace();
		} // END try/catch
	} // END constructor

	/**
	 * Constructor<br/>
	 * @param clazz The class for logging messages.<br/>
	 * @param DCDropletPropertyFileName The property file name to read for DCDroplet properties.<br/>
	 */
	protected DCDropletLogger(final Class<?> clazz, final String DCDropletPropertyFileName) {
		this(null != clazz ? clazz.getName() : "", DCDropletPropertyFileName);
	} // END constructor

	/**
	 * Constructor<br/>
	 * @param name The name for logging messages.<br/>
	 * @param DCDropletPropertyFileName The property file name to read for DCDroplet properties.<br/>
	 */
	protected DCDropletLogger(final String name, final String DCDropletPropertyFileName) {
		this.name = name;

		try {
			properties = new DCDropletProperties(DCDropletPropertyFileName);
		} catch(IOException ioExc) {
			System.out.printf("ERROR in DCDropletLogger: IOException: %s%n", ioExc.getMessage());
			ioExc.printStackTrace();
		} catch(Exception exc) {
			System.out.printf("ERROR in DCDropletLogger: Exception: %s%n", exc.getMessage());
			exc.printStackTrace();
		} // END try/catch
	} // END constructor

	/**
	 * Constructor<br/>
	 * @param clazz The class for logging messages.<br/>
	 * @param DCDropletPropertyFile The file to read for DCDroplet properties.<br/>
	 */
	protected DCDropletLogger(final Class<?> clazz, final File DCDropletPropertyFile) {
		this(null != clazz ? clazz.getName() : "", DCDropletPropertyFile);
	} // END constructor

	/**
	 * Constructor<br/>
	 * @param name The name for logging messages.<br/>
	 * @param DCDropletPropertyFile The file to read for DCDroplet properties.<br/>
	 */
	protected DCDropletLogger(final String name, final File DCDropletPropertyFile) {
		this.name = name;

		try {
			properties = new DCDropletProperties(DCDropletPropertyFile);
		} catch(IOException ioExc) {
			System.out.printf("ERROR in DCDropletLogger: IOException: %s%n", ioExc.getMessage());
			ioExc.printStackTrace();
		} catch(Exception exc) {
			System.out.printf("ERROR in DCDropletLogger: Exception: %s%n", exc.getMessage());
			exc.printStackTrace();
		} // END try/catch
	} // END constructor

	/**
	 * Returns a new logger instance with no name.<br/>
	 * @return DCDropletLogger A new logger instance with no name.<br/>
	 */
	public static DCDropletLogger getLogger() {
		return new DCDropletLogger();
	} // END getLogger

	/**
	 * Returns a new logger instance with the class name.<br/>
	 * @param clazz The class for logging messages.<br/>
	 * @return DCDropletLogger A new logger instance with the class name.<br/>
	 */
	public static DCDropletLogger getLogger(final Class<?> clazz) {
		return new DCDropletLogger(clazz);
	} // END getLogger

	/**
	 * Returns a new logger instance with the supplied name.<br/>
	 * @param name The name for logging messages.<br/>
	 * @return DCDropletLogger A new logger instance with the supplied name.<br/>
	 */
	public static DCDropletLogger getLogger(final String name) {
		return new DCDropletLogger(name);
	} // END getLogger

	/**
	 * Logs a message to this log&apos;s appender(s).<br/>
	 * @param tag The log tag.<br/>
	 * @param msg The log message.<br/>
	 * @param args Arguments referenced by the format specifiers in the format string. If there are more arguments than format specifiers, the extra arguments are ignored.<br/>
	 */
	public void logf(String tag, String msg, Object... args) {
		log(tag, String.format(msg, args));
	} // END logf

	/**
	 * Logs a message to this log&apos;s appender(s).<br/>
	 * @param tag The log tag.<br/>
	 * @param msg The log message.<br/>
	 * @param locale The locale to apply during formatting. If l is null then no localization is applied.<br/>
	 * @param args Arguments referenced by the format specifiers in the format string. If there are more arguments than format specifiers, the extra arguments are ignored.<br/>
	 */
	public void logf(String tag, String msg, Locale locale, Object... args) {
		log(tag, String.format(locale, msg, args));
	} // END logf

	/**
	 * Logs a message to this log&apos;s appender(s).<br/>
	 * @param tag The log tag.<br/>
	 * @param msg The log message.<br/>
	 */
	public void log(String tag, String msg) {
		if(null != properties && null != tag && null != msg) {
			final long TIME_STAMP = System.currentTimeMillis();

			for(String appender : properties.getAppenders()) {
				AppenderProperties appenderProperties = properties.getAppenderProperties(appender);

				boolean logThisMsg = false;
				String msgFmt = "${message}";

				if(appenderProperties.hasTagsDefinition() && appenderProperties.hasTag(tag)) {
					// Check appender tags
					logThisMsg = true;
				} else if(!appenderProperties.hasTagsDefinition() && properties.hasTag(tag)) {
					// Check general tags
					logThisMsg = true;
				} // END if

				// Does the appender have a specific pattern?
				if(!appenderProperties.hasPatternDefinition()) {
					// Check general pattern
					if(properties.hasPatternDefinition()) {
						msgFmt = properties.getPattern();
					} // END if
				// Check appender specific pattern
				} else {
					msgFmt = appenderProperties.getPatternDefinition();
				} // END if/else

				// Check if the message format has a message token
				if(!msgFmt.contains("${message}")) {
					msgFmt += " ${message}";
				} // END if

				if(logThisMsg) {
					appenderProperties.log(tag, msg, msgFmt, name, TIME_STAMP);
				} // END if
			} // END loop
		} // END if
	} // END log
} // END class DCDropletLogger
